package com.example.diskfilesystem.disk;

import config.Config;
import java.io.IOException;
import java.util.Arrays;

public class FATManager {
    private  Disk disk;
    private  byte[] fat = new byte[Config.BLOCK_COUNT];

    public FATManager(Disk disk) {
        this.disk = disk;
    }

    //读取FAT
    public void load() throws IOException {
        //读取disk中块0的数据
        byte[] fatData1 = disk.readBlock(Config.FAT_BLOCKS);
        //复制到fat[0~63]中
        for (int i = 0; i < Config.BLOCK_SIZE; i++) {
            fat[i] = fatData1[i];
        }

        //读取disk中块1的数据
        byte[] fatData2 = disk.readBlock(Config.FAT_BLOCKS + 1);
        //复制到fat[64~127]中
        for (int i = 0; i < Config.BLOCK_SIZE; i++) {
            fat[i + Config.BLOCK_SIZE] = fatData2[i];
        }
    }

    //上传FAT
    public void save() throws IOException {
        byte[] fatData = new byte[Config.BLOCK_SIZE];
        byte[] fatData2 = new byte[Config.BLOCK_SIZE];
        for (int i = 0; i < Config.BLOCK_SIZE; i++) {
            fatData[i] = (byte) fat[i];
        }
        for (int i = 64; i < Config.BLOCK_SIZE; i++) {
            fatData2[i] = (byte) fat[i + Config.BLOCK_SIZE];
        }
        disk.writeBlock(Config.FAT_BLOCKS, fatData);
        disk.writeBlock(Config.FAT_BLOCKS2, fatData2);
    }

    //分配块（寻找空闲块）
    public int allocateBlock() throws IOException {
        load();
        for (int i = 2; i < Config.BLOCK_COUNT; i++) { // 从数据区开始分配
            if (fat[i] == 0) { // 0 表示空闲
                fat[i] = Config.END;
                save();
                return i;
            }
        }
        return -1; // 无可用块
    }

    //FAT表标记0（删除文件时更新FAT表）
    public void freeChain(int startBlock) throws IOException {
        int current = startBlock;
        while (current != Config.END) {
            int next = fat[current];
            fat[current] = 0;
            current = next;
        }
        save();
    }

    //返回文件占用块的下一个下标
    public int getNextBlock(int blockIndex) {
        return fat[blockIndex];
    }

    //更改文件占用块的下一个下标
    public void setNextBlock(int blockIndex, int nextBlock) throws IOException {
        fat[blockIndex] = (byte) nextBlock;
        save();
    }

    //格式化
    public void format() throws IOException {
        Arrays.fill(fat, (byte) 0);
        save();
    }
    //显示指定块输出信息
    public void printFAT(int startBlock, int endBlock) throws IOException {
        for (int i = startBlock; i <= endBlock; i++) {
            byte[] bytes = disk.readBlock(i);
            for(int j = 0; j < 64; j++){
                System.out.print(i*64+j+":"+bytes[j] + " ");
            }
            System.out.println();
        }
    }

    public Disk getDisk() {
        return disk;
    }

    public void setDisk(Disk disk) {
        this.disk = disk;
    }

    public byte[] getFat() {
        return fat;
    }

    public void setFat(byte[] fat) {
        this.fat = fat;
    }
}
